Rendering and displaying three dimensional (3-D) graphics on screen typically involves many calculations and computations. In a simple graphics system, such computations occur according to some level of cooperative or shared processing by the central processing unit (CPU) and the graphics processing unit (GPU). In an exemplary scenario, after instructions are processed and some initial computations occur in the CPU, a set of coordinate points or vertices that define the object to be rendered are stored in video memory for further processing by the GPU in the graphics pipeline. When graphics programmers develop graphics applications via a set of available graphics APIs, the programmer generally indicates a set of vertices to be operated upon by a set of algorithmic elements. This data is sent into the graphics pipeline, and each vertex is streamed through a fixed set of GPU subunits in the graphics pipeline. One of these subunits, called a tesselator, breaks the graphics data down into simple polygons according to predetermined algorithms designed to efficiently cover the surface of the object being represented. Thereafter, one or more programmable shader units, sometimes referred to as shaders or “shader programs,” can operate on the data and perform specialized operations on graphics data. Shaders can include, for example, vertex shader(s), geometry shader(s) and pixel shader(s).
A single shader can receive different combinations of shader constants, and depending on the combination of particular shader constants that are provided, the output generated by the shader will vary. These shader constants can specify, for example, how pixels are combined, how data is read in and out, and in the case of a texture, how values are extracted from that texture. The process of shading is a computation intensive and complex process. When these specific shaders operate in a graphics pipeline, there are regular bottlenecks due to the operations that occur in each stage.
“State” refers to resources being interpreted by the shader program. At any given instance, the graphics pipeline contains a tremendous amount of dynamic state (rendering state, shaders, shader constant variables, resource/memory bindings, etc.). Different combinations of state enable various simulated materials and visual effects.
One component of this state is a set of shader constants that need to be bound to the GPU before executing a shader program. Because the hardware used to implement the graphics pipeline can be in only one configuration at any given instance, it is desirable to reduce time spent setting state (e.g., shader constants) and issuing commands to the GPU.
Some shaders utilize constant buffers (as opposed to constant registers) which hold groups or aggregations of shader constants. Constant buffers can allow shader constants to be set to the GPU more rapidly since the aggregations of shader constants are grouped together. Notwithstanding these advances, it would be desirable to efficiently manage state to avoid redundant evaluation and device state modification. For example, it would be desirable to provide techniques for efficiently arranging constant buffers (or other resources) used at different shaders to more efficiently set state to the GPU.